package cron

import (
	"bigdevops/src/common"
	"bigdevops/src/models"
	"context"
	"encoding/json"
	"fmt"
	"github.com/gammazero/workerpool"
	"go.uber.org/zap"
	"k8s.io/apimachinery/pkg/util/wait"
	"strings"
	"time"
)

// wait.UntilWithContext k8s 基础库 每隔多长时间去执行一次任务
func (cm *CronManager) NotifyOrderManager(ctx context.Context) error {
	// 每隔 多长时间去执行一下 RunSyncCloudResource ，直到 ctx.Done
	go wait.UntilWithContext(ctx, cm.RunNotifyOrder, time.Duration(cm.Sc.WorkOrderAutoActionC.NotifyRunIntervalSeconds)*time.Second)
	<-ctx.Done()
	cm.Sc.Logger.Info("RunNotifyOrder 收到其他任务退出信号 退出")
	return nil

}

func (cm *CronManager) RunNotifyOrder(ctx context.Context) {
	start := time.Now()
	//serviceAccountName := cm.Sc.WorkOrderAutoActionC.ServiceAccount
	//if serviceAccountName == "" {
	//	cm.Sc.Logger.Error("[工单通知模块]自动执行账号没有配置，退出工单执行")
	//	return
	//}
	//
	////currentFlowNode := fmt.Sprintf("用户@%v", serviceAccountName)
	pendingOrders, count, err := models.GetWorkOrderInstanceUnfinished([]string{common.WorkOrderInstanceStatusFinished, common.WorkOrderInstanceStatusApprovalReject})
	if err != nil {
		cm.Sc.Logger.Error("[工单通知模块]扫描数据库中待执行的工单失败",
			zap.Error(err),
		)
		return
	}
	cm.Sc.Logger.Info("[工单通知模块]扫描数据库中待执行的总数",
		zap.Int64("总数", count),
	)

	wp := workerpool.New(cm.Sc.WorkOrderAutoActionC.BatchNum)
	for _, pendingOrder := range pendingOrders {
		pendingOrder := pendingOrder
		wp.Submit(func() {
			// 启动任务
			cm.RunNotifyOrderOne(pendingOrder)
		})
	}
	wp.StopWait()
	tookSeconds := time.Since(start).Seconds()
	cm.Sc.Logger.Info("[工单自动执行]扫描数据库中待执行的耗时",
		zap.Float64("秒数", tookSeconds),
		zap.Int64("总数", count),
	)
}

func (cm *CronManager) RunNotifyOrderOne(pendingOrder *models.WorkOrderInstance) {
	cm.Sc.Logger.Info("[工单通知模块]单条打印",
		zap.Any("name", pendingOrder.Name),
	)
	// 写死
	pendingOrder.FillFrontAllData()
	template := pendingOrder.Template
	if template == nil {
		return
	}
	// 这里的共性是找到下一个节点 遍历通知他们需要动作
	// 处理时间轴
	var actualFlowData []models.FlowNode
	err := json.Unmarshal([]byte(pendingOrder.ActualFlowData), &actualFlowData)
	if err != nil {
		cm.Sc.Logger.Error("[工单通知模块]解析时间轴数据json错误",
			zap.Any("工单名称", pendingOrder.Name),
			zap.Error(err))
		return
	}
	// 找到下一个未执行的节点
	tarGetNode := models.FlowNode{}
	for _, node := range actualFlowData {
		node := node
		if node.ActualUser == "" {
			tarGetNode = node
			break
		}
	}

	// 找到要通知的组或人
	targetUsers := []*models.User{}
	splits := strings.Split(tarGetNode.DefineUserOrGroup, "@")

	switch splits[0] {
	case "用户":
		userName := splits[1]
		dbUser, err := models.GetUserByUserName(userName)
		if err != nil {
			cm.Sc.Logger.Error("[工单通知模块]解析通知节点用户 查找失败",
				zap.Error(err),
			)
			return
		}
		targetUsers = append(targetUsers, dbUser)

	case "组":
		roleValue := splits[1]
		role, err := models.GetRoleByRoleValue(roleValue)
		if err != nil {
			cm.Sc.Logger.Error("[工单通知模块]解析通知节点 组 查找失败",
				zap.Error(err),
			)
			return
		}
		targetUsers = append(targetUsers, role.Users...)

	}

	detailUrl := fmt.Sprintf("%s%s%d",
		cm.Sc.Domain,
		cm.Sc.WorkOrderAutoActionC.DetailUri,
		pendingOrder.ID,
	)
	// 拼接通知消息
	notifyMsg := fmt.Sprintf("您有[%v]工单\n"+
		"[名称:%v] [创建人:%v]\n"+
		"期望完成时间:%v\n"+
		"工单详情连接:%v",
		common.WorkOrderInstanceStatus_MAP[pendingOrder.Status],
		pendingOrder.Name,
		pendingOrder.CreateUserName,
		pendingOrder.DesireFinishTime,
		detailUrl,
	)
	// 遍历通知
	for _, user := range targetUsers {
		user := user
		imc := cm.Sc.ImDingDingC
		imc.AtMobiles = []string{user.Mobile}
		imc.Title = fmt.Sprintf("待处理工单提醒:尊敬的用户:%v", user.Username)
		common.DingDingMsgDirectSend(imc, notifyMsg)
	}

}
